﻿using Common.Extension;
using System.Text;

namespace DesignModeConsole.行为型.备忘录模式;

/// <summary>
/// 描述一个接收命令行的输入，输入文本的时候追加，然后输入:list的时候查询内容，输入:undo的时候会撤销上一次输入的文本
/// 针对上个方法的重构：1.快照的类不让进行修改操作  2.不该暴露出来不需要暴露的方法
/// </summary>
public class RestoreSample1
{
    public void Main()
    {
        var inputText = new RestoreInputText();
        var snapshotsHolder = new RestoreSnapshotHolder();
        // 根据输入值的不同 判断当前是要查询列表还是要还原上一层还是要追加内容
        while (true)
        {
            var scanner = Console.ReadLine();
            if (scanner.IsNullOrWhiteSpace())
                break;

            switch (scanner)
            {
                case ":list": // 查询列表
                    Console.WriteLine(inputText.GetText());
                    break;

                case ":undo": // 撤回上次的修改
                    {
                        var snapshot = snapshotsHolder.PopSnapshot();
                        inputText.RestoreText(snapshot.Text);
                        break;
                    }
                default: // 添加内容
                    snapshotsHolder.PushSnapshot(inputText.CreateSnapshot());
                    inputText.Append(scanner);
                    break;
            }
        }
    }
}

public class RestoreInputText
{
    private readonly StringBuilder _text = new StringBuilder();

    /// <summary>
    /// 获取文本的值
    /// </summary>
    /// <returns></returns>
    public string GetText()
    {
        return _text.ToString();
    }

    /// <summary>
    /// 追加内容
    /// </summary>
    /// <param name="input"></param>
    public void Append(string input)
    {
        _text.Append(input);
    }

    public SnapshotDto CreateSnapshot()
    {
        return new SnapshotDto(_text.ToString());
    }

    /// <summary>
    /// 恢复对象
    /// </summary>
    /// <param name="text"></param>
    public void RestoreText(string text)
    {
        this._text.Clear();
        this._text.Append(text);
    }
}

/// <summary>
/// 快照持有者
/// </summary>
public class RestoreSnapshotHolder
{
    /// <summary>
    /// 记录每次的变更的快照信息
    /// </summary>
    private readonly Stack<SnapshotDto> _snapsShots = new Stack<SnapshotDto>();

    public SnapshotDto PopSnapshot()
    {
        return _snapsShots.Pop();
    }

    /// <summary>
    /// 存储上一次输入的值
    /// </summary>
    /// <param name="inputText"></param>
    public void PushSnapshot(SnapshotDto inputText)
    {
        var deepClonedInputText = new SnapshotDto(inputText.Text);
        _snapsShots.Push(deepClonedInputText);
    }
}

public class SnapshotDto
{
    public SnapshotDto(string text)
    {
        Text = text;
    }

    public string Text { get; private set; }
}